#ifndef _H_HFILE
#define _H_HFILE

#include <stddef.h>
#include "hplatform.h"

#ifdef __cplusplus
extern "C" {
#endif // #ifdef __cplusplus

#define HOA_READ                        0x00000001
#define HOA_WRITE                       0x00000002
#define HOF_CREATE                      1           // create file if file not exist, truncate it otherwise
#define HOF_NEW                         2           // create file if file not exist, failed otherwise
#define HOF_OPEN                        3           // open an existing file, failed if file not exist
#define HOF_TRUNCATE                    4           // open an existing file and truncate it, failed if file not exist
#define HF_INVALID_FILE                 (hfile_t)-1
#define HF_OPERATION_FAILED             -1
#define HOM_BEGIN                       1
#define HOM_CURRENT                     2
#define HOM_END                         3

#if _MSC_VER
#  include <Windows.h>
typedef HANDLE hfile_t;
typedef long long hfile_off_t;
#else // #if _MSC_VER
#  include <unistd.h>
typedef int hfile_t;
typedef off_t hfile_off_t;
#endif // #if _MSC_VER

// open file, returned HF_INVALID_FILE if failed
// file_access can be FOA_READ FOA_WRITE
// flags must be one of HOF_CREATE HOF_NEW HOF_OPEN HOF_TRUNCATE
hfile_t HPLATFORMCALL hfile_open(const char* file_name, int file_access, int flags);
#if _MSC_VER
hfile_t HPLATFORMCALL hfile_open16(const wchar_t* file_name, int file_access, int flags);
#endif

// close file opened by hfile_open
int HPLATFORMCALL hfile_close(hfile_t file);

// read file, returned number of bytes readed, returned zero when end of file occurs, and -1 means operation failed
int HPLATFORMCALL hfile_read(hfile_t file, char* buff, int buf_size);

// write file, returned number of bytes writed, returned -1 when operation failed
int HPLATFORMCALL hfile_write(hfile_t file, const char* buff, int buf_size);

// get file size, returned -1 when operation failed
hfile_off_t HPLATFORMCALL hfile_getsize(hfile_t file);

// truncate file to current offset
int HPLATFORMCALL hfile_truncate(hfile_t file);

// set file offset, method can be one of HOM_BEGIN HOM_CURRENT HOM_END, if user use invalid method,
// function use HOM_BEGIN instead. the return value is new file offset
hfile_off_t HPLATFORMCALL hfile_offset(hfile_t file, hfile_off_t offset, int method);

// copy file, if to_this is exist, overwrite it
int HPLATFORMCALL hfile_copy(const char* copy_this, const char* to_this);
#if _MSC_VER
int HPLATFORMCALL hfile_copy16(const wchar_t* copy_this, const wchar_t* to_this);
#endif // #if _MSC_VER

// move file, if to_this exist, overwrite it
int HPLATFORMCALL hfile_move(const char* move_this, const char* to_this);
#if _MSC_VER
int HPLATFORMCALL hfile_move16(const wchar_t* move_this, const wchar_t* to_this);
#endif // #if _MSC_VER

int HPLATFORMCALL hfile_delete(const char* delete_this);
#if _MSC_VER
int HPLATFORMCALL hfile_delete16(const wchar_t* delete_this);
#endif // #if _MSC_VER
// flush cached data to storage device
int HPLATFORMCALL hfile_sync(hfile_t file);
    
#ifdef __cplusplus
}
#endif // #ifdef __cplusplus

#endif // #ifndef _H_HFILE
